package dev;

import io.netty.buffer.ByteBuf;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Author :  Rocky
 * Date : 12/06/2017 17:31
 * Description :
 * Test :
 */
public class RecordMeta {

    //key   : 列名
    //value : 相对于整行记录开始而言的偏移量，单位byte
    public static final Map<String, Integer> fieldsOffset = new HashMap<>();

    //key   : 列名
    //value : 数据类型：
    public static final Map<String, String> fieldsDataTypeMap = new HashMap<>();

    //保存的数据和 fieldsDataTypeMap 一样的
    public static final List<MapEntry> fieldsDataTypeList = new ArrayList<>();

    //每条消息大小
    public static int sizePerRecord;

    //key   : 列名
    //value : 列名对应的byte
    private static final Map<String, Byte> fieldNameToByte = new HashMap<>();

    //key   : 列名对应的byte
    //value : 列名
    private static final Map<Byte, String> byteToFieldName = new HashMap<>();


    public static void addFieldDataType(final String colunmName, final String dataType) {
        fieldsDataTypeMap.put(colunmName, dataType);
        fieldsDataTypeList.add(new MapEntry(colunmName, dataType));
    }


    public static void encodeFieldNames() {
        int i = 0;
        for (String fieldName : fieldsDataTypeMap.keySet()) {
            byte b = (byte) i++;
            fieldNameToByte.put(fieldName, b);
            byteToFieldName.put(b, fieldName);
        }
    }

    public static byte encodeFieldName(String fieldName) {
        return fieldNameToByte.get(fieldName);
    }

    public static String decodeFieldName(Byte code) {
        return byteToFieldName.get(code);
    }


    ///////////////////////////////


    //1代表为数字类型
    public static final String NUM_DATA_TYPE = "1";

    //2代表为字符串类型
    public static final String STR_DATA_TYPE = "2";

    //3代表为主键
    public static final String PK_DATA_TYPE = "3";

    public static byte encodeDataType(String dataType) {
        if (NUM_DATA_TYPE.equals(dataType)) {
            return 1;
        }
        if (STR_DATA_TYPE.equals(dataType)) {
            return 2;
        }
        if (PK_DATA_TYPE.equals(dataType)) {
            return 3;
        }
        throw new RuntimeException("不支持的数据类型");
    }


    public static ByteBuf encode() {
        ByteBuf result = MiscUtils.directBuffer(1024);

        //长度占位
        result.writerIndex(4);

        //对 sizePerRecord 编码
        result.writeByte(sizePerRecord);

        //对 字段个数 编码
        result.writeByte(fieldsOffset.size());

        //对 字段名 , 数据类型 和 偏移量 进行编码
        for (MapEntry mapEntry : fieldsDataTypeList) {

            String columnName = (String) mapEntry.getKey();
            String dataType = (String) mapEntry.getValue();
            Integer offset = fieldsOffset.get(columnName);

            byte[] columnNameBytes = columnName.getBytes();
            byte[] dataTypeBytes = dataType.getBytes();

            //写字段名
            result.writeByte(columnNameBytes.length);
            result.writeBytes(columnNameBytes);

            //写数据类型
            result.writeByte(dataTypeBytes.length);
            result.writeBytes(dataTypeBytes);

            //写偏移量
            result.writeByte(offset);
        }

        result.setInt(0, result.writerIndex());
        return result;
    }

    public static void decode(ByteBuf bb) {

        //注意这里不用读长度，因为网络传输后，长度字段设置的是自动丢弃

        //读 sizePerRecord
        sizePerRecord = bb.readByte();

        //读 字段个数
        int fieldCount = bb.readByte();

        //读 字段名 , 数据类型 和 偏移量
        for (int i = 0; i < fieldCount; i++) {

            //读 字段名
            byte columnNameByteSize = bb.readByte();
            byte[] strBytes = new byte[columnNameByteSize];
            bb.readBytes(strBytes);
            String columnName = new String(strBytes);

            //读 数据类型
            byte dataTypeByteSize = bb.readByte();
            strBytes = new byte[dataTypeByteSize];
            bb.readBytes(strBytes);
            String dataType = new String(strBytes);
//            String dataType = bb.readCharSequence(dataTypeByteSize, Charset.forName("utf-8")).toString();

            //读 偏移量
            int offset = bb.readByte();

            fieldsOffset.put(columnName, offset);

            addFieldDataType(columnName, dataType);
        }

        bb.clear();
    }

    public static String getInfo() {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.append("sizePerRecord=").append(sizePerRecord).append("\n");
        //对 字段名 , 数据类型 和 偏移量 进行编码
        for (MapEntry mapEntry : fieldsDataTypeList) {

            String columnName = (String) mapEntry.getKey();
            String dataType = (String) mapEntry.getValue();
            Integer offset = fieldsOffset.get(columnName);

            strBuilder.append(columnName).append("     ").append(dataType).append("     ").append(offset).append("\n");
        }
        return strBuilder.toString();
    }

}
